//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Target Devices:
// Tool versions:
//
// Create Date:    2011-08-18 15:28
// Project Name:
// Description: 1. if simulation is true,use mcb_bfm to write gui data to ddr.
//
// Dependencies:
//
// Revision: 1.0
// Revision 0.01 - File Created
//
//
//////////////////////////////////////////////////////////////////////////////////

`timescale 1ps/1ps
module jrmoc_cmos
#(
    parameter SIMULATION = "FALSE",
    parameter H_SIZE  = 240,
    parameter V_SIZE  = 320
)
(
    input           clk,            // external 20MHz
    input           rst,

    // ARM EBI interface
    inout [15:0]    ebi_d,
    input [25:0]    ebi_a,
    input           ebi_ncs,
    input           ebi_nrd,
    input           ebi_nwe,

    // CAM_X
    output          cam_x_mclk,
    input [7:0]     cam_x_d,
    input           cam_x_vsync,
    input           cam_x_hsync,
    input           cam_x_href,
    input           cam_x_pclk,

    // CAM_Y
    output          cam_y_mclk,
    input [7:0]     cam_y_d,
    input           cam_y_vsync,
    input           cam_y_hsync,
    input           cam_y_href,
    input           cam_y_pclk,

    // LCD
    output [7:0]    lcd_r,
    output [7:0]    lcd_g,
    output [7:0]    lcd_b,
    output          lcd_spclk,
    output          lcd_de,
    output          lcd_hsync,
    output          lcd_vsync,

    // DDR2
    inout [15:0]    f_ddr_d,
    output [12:0]   f_ddr_a,
    output          f_ddr_cke,
    output          f_ddr_we,
    output [1:0]    f_ddr_ba,
    output          f_ddr_clk,
    output          f_ddr_nclk,
    output          f_ddr_ras,
    output          f_ddr_cas,
    output          f_ddr_odt,
    inout           f_ddr_udqs,
    inout           f_ddr_udqsn,
    inout           f_ddr_ldqs,
    inout           f_ddr_ldqsn,
    input           f_ddr_udqm,
    input           f_ddr_ldqm,
    inout           mcb1_rzq,
    inout           mcb1_zio,
    input           f_ddr_vref
);

/********************************************************\
Parameter
\********************************************************/
parameter DDR_WR        = 3'b000;
parameter DDR_RD        = 3'b001;
parameter DDR_BUF0_ADDR = 30'h0;
parameter DDR_BUF1_ADDR = 30'h1_2C00;


/********************************************************\
Signals
\********************************************************/

wire                        c1_clk0;
wire                        c1_clk1;
wire                        c1_clk2;
wire                        c1_rst0;
(* KEEP = "TRUE" *) wire    cam_x_pclk_o;
(* KEEP = "TRUE" *) wire    cam_y_pclk_o;

// gui wr ddr port
wire                    gui_c1_cmd_clk;
wire                    gui_c1_cmd_en;
wire [2:0]              gui_c1_cmd_instr;
wire [5:0]              gui_c1_cmd_bl;
wire [29:0]             gui_c1_cmd_byte_addr;
wire                    gui_c1_cmd_full;

wire                    gui_c1_wr_clk;
wire                    gui_c1_wr_en;
wire [3:0]              gui_c1_wr_mask;
wire [31:0]             gui_c1_wr_data;
wire                    gui_c1_wr_full;

// cmos x
wire                    cmos_x_cmd_clk;
wire                    cmos_x_cmd_en;
wire [2:0]              cmos_x_cmd_instr;
wire [5:0]              cmos_x_cmd_bl;
wire [29:0]             cmos_x_cmd_byte_addr;
wire                    cmos_x_cmd_full;

wire                    cmos_x_wr_clk;
wire                    cmos_x_wr_en;
wire [3:0]              cmos_x_wr_mask;
wire [31:0]             cmos_x_wr_data;
wire                    cmos_x_wr_full;

wire [1:0]              x_buf_done;

// cmos y
wire                    cmos_y_cmd_clk;
wire                    cmos_y_cmd_en;
wire [2:0]              cmos_y_cmd_instr;
wire [5:0]              cmos_y_cmd_bl;
wire [29:0]             cmos_y_cmd_byte_addr;
wire                    cmos_y_cmd_full;

wire                    cmos_y_wr_clk;
wire                    cmos_y_wr_en;
wire [3:0]              cmos_y_wr_mask;
wire [31:0]             cmos_y_wr_data;
wire                    cmos_y_wr_full;

wire [1:0]              y_buf_done;

// lcd rd ddr port
wire                    lcd_cmd_clk;
wire                    lcd_cmd_en;
wire [2:0]              lcd_cmd_instr;
wire [5:0]              lcd_cmd_bl;
wire [29:0]             lcd_cmd_byte_addr;
wire                    lcd_cmd_full;

wire                    lcd_rd_clk;
wire                    lcd_rd_en;
wire                    lcd_rd_empty;
wire [31:0]             lcd_rd_data;

// BRAM wr port
wire                    buffer_x_clk;
wire                    buffer_x_wr;
wire [16:0]             buffer_x_addr;
wire [7:0]              buffer_x_d;
wire                    buffer_y_clk;
wire                    buffer_y_wr;
wire [16:0]             buffer_y_addr;
wire [7:0]              buffer_y_d;

// ARM EBI config
wire [15:0]             offset_v;
wire [15:0]             offset_h;
wire [15:0]             disp_mode;
wire [15:0]             gui_id;
wire [15:0]             edge_pos;

/********************************************************\
main code
\********************************************************/

IBUFG  u_ibufg_x_pclk
(
    .I  (cam_x_pclk),
    .O  (cam_x_pclk_o)
);

IBUFG  u_ibufg_y_pclk
(
    .I  (cam_y_pclk),
    .O  (cam_y_pclk_o)
);

ODDR2 u_oddr2_cam_x(
      .Q(cam_x_mclk),   // 1-bit DDR output data
      .C0(c1_clk1),   // 1-bit clock input
      .C1(~c1_clk1),   // 1-bit clock input
      .CE(1'b1), // 1-bit clock enable input
      .D0(1'b1), // 1-bit data input (associated with C0)
      .D1(1'b0)  // 1-bit data input (associated with C1)
);

ODDR2 u_oddr2_cam_y(
      .Q(cam_y_mclk),   // 1-bit DDR output data
      .C0(c1_clk2),   // 1-bit clock input
      .C1(~c1_clk2),   // 1-bit clock input
      .CE(1'b1), // 1-bit clock enable input
      .D0(1'b1), // 1-bit data input (associated with C0)
      .D1(1'b0)  // 1-bit data input (associated with C1)
);

// synthesis translate_off
mcb_bfm gui_wr
(
    .clk                        (c1_clk0),

    .ddr_cmd_clk                (gui_c1_cmd_clk),
    .ddr_cmd_en                 (gui_c1_cmd_en),
    .ddr_cmd_instr              (gui_c1_cmd_instr),
    .ddr_cmd_bl                 (gui_c1_cmd_bl),
    .ddr_cmd_byte_addr          (gui_c1_cmd_byte_addr),
    .ddr_cmd_empty              (),
    .ddr_cmd_full               (gui_c1_cmd_full),

    // write port
   .ddr_wr_clk                  (gui_c1_wr_clk),
   .ddr_wr_en                   (gui_c1_wr_en),
   .ddr_wr_mask                 (gui_c1_wr_mask),
   .ddr_wr_data                 (gui_c1_wr_data),
   .ddr_wr_full                 (gui_c1_wr_full),
   .ddr_wr_empty                (),
   .ddr_wr_count                (),
   .ddr_wr_underrun             (),
   .ddr_wr_error                ()
);

// synthesis translate_on

// CMOS X
cmos_intf
#(
    .H_SIZE(H_SIZE),
    .V_SIZE(V_SIZE)
)
cmos_x
(
    .clk                    (c1_clk0),
    .rst                    (c1_rst0),

    // config & status
    .cmos_id                (1'b0),
    .offset_h               (offset_h),
    .offset_v               (offset_v),
    .ddr_buf0_addr          (DDR_BUF0_ADDR),
    .ddr_buf1_addr          (DDR_BUF1_ADDR),
    .ddr_buf_done           (x_buf_done),
    .status                 (),

    // CAM
    .cam_mclk               (),
    .cam_d                  (cam_x_d),
    .cam_vsync              (cam_x_vsync),
    .cam_hsync              (cam_x_hsync),
    .cam_href               (cam_x_href),
    .cam_pclk               (cam_x_pclk_o),

    //cmos ddr write
    .cmos_cmd_clk           (cmos_x_cmd_clk),
    .cmos_cmd_en            (cmos_x_cmd_en),
    .cmos_cmd_instr         (),
    .cmos_cmd_bl            (cmos_x_cmd_bl),
    .cmos_cmd_byte_addr     (cmos_x_cmd_byte_addr),
    .cmos_cmd_full          (cmos_x_cmd_full),

    .cmos_wr_clk            (cmos_x_wr_clk),
    .cmos_wr_en             (cmos_x_wr_en),
    .cmos_wr_mask           (cmos_x_wr_mask),
    .cmos_wr_data           (cmos_x_wr_data),
    .cmos_wr_full           (cmos_x_wr_full),

     //Frame buffer write port
    .buffer_clk             (buffer_x_clk),
    .buffer_wr              (buffer_x_wr),
    .buffer_addr            (buffer_x_addr),
    .buffer_d               (buffer_x_d)
);

// CMOS Y
cmos_intf
#(
    .H_SIZE(H_SIZE),
    .V_SIZE(V_SIZE)
)
cmos_y
(
    .clk                    (c1_clk0),
    .rst                    (c1_rst0),

    // config & status
    .cmos_id                (1'b1),
    .offset_h               (offset_h),
    .offset_v               (offset_v),
    .ddr_buf0_addr          (DDR_BUF0_ADDR),
    .ddr_buf1_addr          (DDR_BUF1_ADDR),
    .ddr_buf_done           (y_buf_done),
    .status                 (),

    // CAM
    .cam_mclk               (),
    .cam_d                  (cam_y_d),
    .cam_vsync              (cam_y_vsync),
    .cam_hsync              (cam_y_hsync),
    .cam_href               (cam_y_href),
    .cam_pclk               (cam_y_pclk_o),

    //cmos ddr write
    .cmos_cmd_clk           (cmos_y_cmd_clk),
    .cmos_cmd_en            (cmos_y_cmd_en),
    .cmos_cmd_instr         (),
    .cmos_cmd_bl            (cmos_y_cmd_bl),
    .cmos_cmd_byte_addr     (cmos_y_cmd_byte_addr),
    .cmos_cmd_full          (cmos_y_cmd_full),

    .cmos_wr_clk            (cmos_y_wr_clk),
    .cmos_wr_en             (cmos_y_wr_en),
    .cmos_wr_mask           (cmos_y_wr_mask),
    .cmos_wr_data           (cmos_y_wr_data),
    .cmos_wr_full           (cmos_y_wr_full),

     //Frame buffer write port
    .buffer_clk             (buffer_y_clk),
    .buffer_wr              (buffer_y_wr),
    .buffer_addr            (buffer_y_addr),
    .buffer_d               (buffer_y_d)
);

generate
	if (SIMULATION == "FALSE")
        arm_ebi # (
        .ADDR_WIDTH(26),
        .DATA_WIDTH(16)
        ) u_ebi (
            .clk                (c1_clk0),
            .rst                (c1_rst0),

            // ebi interface
            .ebi_d              (ebi_d),
            .ebi_a              (ebi_a),
            .ebi_ncs            (ebi_ncs),
            .ebi_nrd            (ebi_nrd),
            .ebi_nwe            (ebi_nwe),

            // control and status reg
            .disp_mode          (disp_mode),
            .offset_h           (offset_h),
            .offset_v           (offset_v),
            .gui_sel            (gui_id),
            .edge_pos           (edge_pos),
            
            //ddr write
            .c1_cmd_clk         (gui_c1_cmd_clk),
            .c1_cmd_en          (gui_c1_cmd_en),
            .c1_cmd_instr       (gui_c1_cmd_instr),
            .c1_cmd_bl          (gui_c1_cmd_bl),
            .c1_cmd_byte_addr   (gui_c1_cmd_byte_addr),
            .c1_cmd_full        (gui_c1_cmd_full),

            .c1_wr_clk          (gui_c1_wr_clk),
            .c1_wr_en           (gui_c1_wr_en),
            .c1_wr_mask         (gui_c1_wr_mask),
            .c1_wr_data         (gui_c1_wr_data),
            .c1_wr_full         (gui_c1_wr_full),

             //Frame buffer write port
            .buffer_x_clk       (buffer_x_clk),
            .buffer_x_wr        (buffer_x_wr),
            .buffer_x_addr      (buffer_x_addr),
            .buffer_x_d         (buffer_x_d),
            .buffer_y_clk       (buffer_y_clk),
            .buffer_y_wr        (buffer_y_wr),
            .buffer_y_addr      (buffer_y_addr),
            .buffer_y_d         (buffer_y_d)
        );
    else
        arm_ebi # (
        .ADDR_WIDTH(26),
        .DATA_WIDTH(16)
        ) u_ebi (
            .clk                (c1_clk0),
            .rst                (c1_rst0),

            // ebi interface
            .ebi_d              (ebi_d),
            .ebi_a              (ebi_a),
            .ebi_ncs            (ebi_ncs),
            .ebi_nrd            (ebi_nrd),
            .ebi_nwe            (ebi_nwe),

            // control and status reg
            .disp_mode          (disp_mode),
            .offset_h           (offset_h),
            .offset_v           (offset_v),
            .gui_sel            (gui_id),
            .edge_pos           (edge_pos),
            
             //Frame buffer write port
            .buffer_x_clk       (buffer_x_clk),
            .buffer_x_wr        (buffer_x_wr),
            .buffer_x_addr      (buffer_x_addr),
            .buffer_x_d         (buffer_x_d),
            .buffer_y_clk       (buffer_y_clk),
            .buffer_y_wr        (buffer_y_wr),
            .buffer_y_addr      (buffer_y_addr),
            .buffer_y_d         (buffer_y_d)
        );
endgenerate

sobel_top #(
    .H_SIZE(H_SIZE),
    .V_SIZE(V_SIZE)
) u_sobel(
    .cam_pclk       (buffer_x_clk),    // use cam_pclk
    .sys_clk        (c1_clk0),
    .rst            (cam_x_vsync),
    .wrreq          (buffer_x_wr),
    .wrdata         (buffer_x_d),
    .out_data       (edge_pos)
);

ddr_ctrl # (
    .C1_P0_MASK_SIZE(4),
    .C1_P0_DATA_PORT_SIZE(32),
    .C1_P1_MASK_SIZE(4),
    .C1_P1_DATA_PORT_SIZE(32),
    .DEBUG_EN(0),
    .C1_MEMCLK_PERIOD(5000),
    .C1_CALIB_SOFT_IP("TRUE"),
    .C1_SIMULATION("TRUE"),
    .C1_RST_ACT_LOW(0),
    .C1_INPUT_CLK_TYPE("SINGLE_ENDED"),
    .C1_MEM_ADDR_ORDER("ROW_BANK_COLUMN"),
    .C1_NUM_DQ_PINS(16),
    .C1_MEM_ADDR_WIDTH(13),
    .C1_MEM_BANKADDR_WIDTH(2)
)
design_top (

  .c1_sys_clk               (clk),
  .c1_sys_rst_i             (rst),

  .mcb1_dram_dq             (f_ddr_d),
  .mcb1_dram_a              (f_ddr_a),
  .mcb1_dram_ba             (f_ddr_ba),
  .mcb1_dram_ras_n          (f_ddr_ras),
  .mcb1_dram_cas_n          (f_ddr_cas),
  .mcb1_dram_we_n           (f_ddr_we),
  .mcb1_dram_odt            (f_ddr_odt),
  .mcb1_dram_cke            (f_ddr_cke),
  .mcb1_dram_ck             (f_ddr_clk),
  .mcb1_dram_ck_n           (f_ddr_nclk),
  .mcb1_dram_dqs            (f_ddr_ldqs),
  .mcb1_dram_dqs_n          (f_ddr_ldqsn),
  .mcb1_dram_udqs           (f_ddr_udqs),    // for X16 parts
  .mcb1_dram_udqs_n         (f_ddr_udqsn),  // for X16 parts
  .mcb1_dram_udm            (f_ddr_udqm),     // for X16 parts
  .mcb1_dram_dm             (f_ddr_ldqm),

  .c1_clk0                  (c1_clk0),
  .c1_clk1                  (c1_clk1),
  .c1_clk2                  (c1_clk2),
  .c1_rst0                  (c1_rst0),
  .c1_calib_done            (c1_calib_done),

  .mcb1_rzq                 (mcb1_rzq),
  .mcb1_zio                 (mcb1_zio),

    // CMOS X
   .c1_p2_cmd_clk                          (cmos_x_cmd_clk),
   .c1_p2_cmd_en                           (cmos_x_cmd_en),
   .c1_p2_cmd_instr                        (DDR_WR),
   .c1_p2_cmd_bl                           (cmos_x_cmd_bl),
   .c1_p2_cmd_byte_addr                    (cmos_x_cmd_byte_addr),
   .c1_p2_cmd_empty                        (),
   .c1_p2_cmd_full                         (cmos_x_cmd_full),

   .c1_p2_wr_clk                           (cmos_x_wr_clk),
   .c1_p2_wr_en                            (cmos_x_wr_en),
   .c1_p2_wr_mask                          (cmos_x_wr_mask),
   .c1_p2_wr_data                          (cmos_x_wr_data),
   .c1_p2_wr_full                          (cmos_x_wr_full),
   .c1_p2_wr_empty                         (),
   .c1_p2_wr_count                         (),
   .c1_p2_wr_underrun                      (),
   .c1_p2_wr_error                         (),

    // CMOS Y
   .c1_p3_cmd_clk                          (cmos_y_cmd_clk),
   .c1_p3_cmd_en                           (cmos_y_cmd_en),
   .c1_p3_cmd_instr                        (DDR_WR),
   .c1_p3_cmd_bl                           (cmos_y_cmd_bl),
   .c1_p3_cmd_byte_addr                    (cmos_y_cmd_byte_addr),
   .c1_p3_cmd_empty                        (),
   .c1_p3_cmd_full                         (cmos_y_cmd_full),

   .c1_p3_wr_clk                           (cmos_y_wr_clk),
   .c1_p3_wr_en                            (cmos_y_wr_en),
   .c1_p3_wr_mask                          (cmos_y_wr_mask),
   .c1_p3_wr_data                          (cmos_y_wr_data),
   .c1_p3_wr_full                          (cmos_y_wr_full),
   .c1_p3_wr_empty                         (),
   .c1_p3_wr_count                         (),
   .c1_p3_wr_underrun                      (),
   .c1_p3_wr_error                         (),

   // ARM EBI write gui data
   .c1_p4_cmd_clk                          (gui_c1_cmd_clk),
   .c1_p4_cmd_en                           (gui_c1_cmd_en),
   .c1_p4_cmd_instr                        (DDR_WR),
   .c1_p4_cmd_bl                           (gui_c1_cmd_bl),
   .c1_p4_cmd_byte_addr                    (gui_c1_cmd_byte_addr),
   .c1_p4_cmd_empty                        (),
   .c1_p4_cmd_full                         (gui_c1_cmd_full),
   .c1_p4_wr_clk                           (gui_c1_wr_clk),
   .c1_p4_wr_en                            (gui_c1_wr_en),
   .c1_p4_wr_mask                          (gui_c1_wr_mask),
   .c1_p4_wr_data                          (gui_c1_wr_data),
   .c1_p4_wr_full                          (gui_c1_wr_full),
   .c1_p4_wr_empty                         (),
   .c1_p4_wr_count                         (),
   .c1_p4_wr_underrun                      (),
   .c1_p4_wr_error                         (),

   // LCD read video buffer data
   .c1_p5_cmd_clk                          (lcd_cmd_clk),
   .c1_p5_cmd_en                           (lcd_cmd_en),
   .c1_p5_cmd_instr                        (DDR_RD),
   .c1_p5_cmd_bl                           (lcd_cmd_bl),
   .c1_p5_cmd_byte_addr                    (lcd_cmd_byte_addr),
   .c1_p5_cmd_empty                        (lcd_cmd_empty),
   .c1_p5_cmd_full                         (lcd_cmd_full),

   .c1_p5_rd_clk                           (lcd_rd_clk),
   .c1_p5_rd_en                            (lcd_rd_en),
   .c1_p5_rd_data                          (lcd_rd_data),
   .c1_p5_rd_full                          (lcd_rd_full),
   .c1_p5_rd_empty                         (lcd_rd_empty),
   .c1_p5_rd_count                         (),
   .c1_p5_rd_overflow                      (),
   .c1_p5_rd_error                         ()
);

lcd_ctrl
#(
    .H_SIZE(H_SIZE),
    .V_SIZE(V_SIZE)
)
u_lcd(
    .clk                (c1_clk0),
    .rst                (c1_rst0),

    // config & status
    .x_buff_done        (x_buf_done),
    .y_buff_done        (y_buf_done),
    .disp_mode          (disp_mode),
    .gui_id             (gui_id),
    .status             (),

    //ddr buffer read
    .ddr_cmd_clk        (lcd_cmd_clk),
    .ddr_cmd_en         (lcd_cmd_en),
    .ddr_cmd_instr      (lcd_cmd_instr),
    .ddr_cmd_bl         (lcd_cmd_bl),
    .ddr_cmd_byte_addr  (lcd_cmd_byte_addr),
    .ddr_cmd_full       (lcd_cmd_full),
    .ddr_rd_clk         (lcd_rd_clk),
    .ddr_rd_en          (lcd_rd_en),
    .ddr_rd_empty       (lcd_rd_empty),
    .ddr_rd_data        (lcd_rd_data),

     //LCD port
    .lcd_r              (lcd_r),
    .lcd_g              (lcd_g),
    .lcd_b              (lcd_b),
    .lcd_pclk           (lcd_spclk),
    .lcd_de             (lcd_de),
    .lcd_hsync          (lcd_hsync),
    .lcd_vsync          (lcd_vsync)
);
endmodule
